package libra.custom;

import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;

import reactor.core.publisher.Mono;

/**
 * Gateway集成Sentinel自定义配置类
 */
@Configuration
public class SentinelConfig {
	/*************************************************************
	 * 自定义Gateway集成Sentinel的BlockRequestHandler流控异常处理 *
	 *************************************************************/
	/*
	 * 方式一、通过手动调用，在项目启动时手动执行setBlockHandler()设置
	 */
//	@PostConstruct
//	public void init() {
//		GatewayCallbackManager.setBlockHandler( 
//			new BlockRequestHandler() {
//				@Override
//				public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
//					// 设置返回的状态码
//					return ServerResponse.status( 439 )
//							// 设置返回的信息格式
//							.contentType( MediaType.APPLICATION_JSON )
//							// 设置返回的内容
//							.body(
//								BodyInserters.fromValue( 
//									Map.of( "code", 439, "exType", t.getClass().getSimpleName() ) 
//								) 
//							);
//				}
//			}
//		);
//	}
	
	/*
	 * 方式二、将自定义BlockRequestHandler的实例注册到容器
	 * 	底层SentinelSCGAutoConfiguration会从容器中进行获取，并通过GatewayCallbackManager进行设置
	 * 	com.alibaba.cloud.sentinel.gateway.scg.SentinelSCGAutoConfiguration
	 */
	@Bean
	public BlockRequestHandler createBlockRequestHandler() {
		// 自定义降级、熔断异常处理实现，该处理只对触发降级、熔断的DegradeException异常有效
		return new BlockRequestHandler() {
			@Override
			public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
				// 设置返回的状态码
				return ServerResponse.status( 449 )
						// 设置返回的信息格式
						.contentType( MediaType.APPLICATION_JSON )
						// 设置返回的内容
						.body(
							BodyInserters.fromValue( 
								Map.of( "code", 449, "exType", t.getClass().getSimpleName() ) 
							) 
						);
			}
		};
	}
}

class a {
	
}
